package ihm_clarifiee.application;

import ihm_clarifiee.Control.CProjet;
import ihm_clarifiee.Control.CRelease;
import ihm_clarifiee.Control.CUsine;
import ihm_clarifiee.sauvegarde.CareTaker;
import ihm_clarifiee.sauvegarde.Originator;
import ihm_clarifiee.sauvegarde.Project_State;
import ihm_clarifiee.sauvegarde.Release_State;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * @(#) Release.java
 */
public class Release extends SaveAndRestore<Release_State, Release>
{
	protected ArrayList<Sprint> m_listeSprint;

	private String m_nom;
	private String m_objectif;
	private Date m_dateDebut;
	private Date m_dateFin;
	private Usine u;
	private Projet m_projet;
	
//  Sauvegarde
    private CareTaker<Release_State> careTaker;
    private Originator<Release_State> originator;
    
//    XML
    private static org.jdom.Document document;
	private static Element racine;
	
	public Release (Usine u,Projet projet, String nom, String objectifs, Date dateDebut, Date dateFin){
	
		this.m_projet = projet;
		this.m_listeSprint = new ArrayList<Sprint>();
        this.u=u;
		this.m_nom = nom;
		this.m_objectif = objectifs;
		this.m_dateDebut = dateDebut;
		this.m_dateFin = dateFin;
		
		// On cree tous les sprints, en se basant sur la duree par defaut d'un sprint
		//		On laisse 1 jour entre chaque sprint (inter-sprint)
	
		// Nombre de jours disponibles pour la release
		int nbJours = (int)((dateFin.getTime() - dateDebut.getTime()) / 86400000);
		long dureeSprint = (long)((m_projet.getDureeSprint()-1) * 86400000);
		

		System.out.println("Date debut release : "+this.getDateDebut());
		System.out.println("Date fin release : "+this.getDateFin());
		System.out.println("Duree des sprints : "+this.m_projet.getDureeSprint());
		

		System.out.println("(dateFin.getTime() - dateDebut.getTime())" + (dateFin.getTime() - dateDebut.getTime()));
		System.out.println("dureeSprint" + dureeSprint);
		if ((dateFin.getTime() - dateDebut.getTime()) > dureeSprint) {
			System.out.println("HH");
			for (int i = 0; new Date(dateDebut.getTime() + (i * (dureeSprint + 2*86400000)) + dureeSprint).before(this.m_dateFin); i++) {
				creerSprint(u.newSprint("sprint "+i,
										new Date(dateDebut.getTime() + (i * (dureeSprint + 2*86400000))), 
										new Date(dateDebut.getTime() + (i * (dureeSprint + 2*86400000)) + dureeSprint), 
										""));
				System.out.println("Creation Sprint numero "+i);
			}
			// Ajout du dernier sprint, de duree inferieure aux autres sprints (on prend le nbre de jours qu'il reste)
			// Si le nbre de jours restants est insuffisant, on renomme le dernier sprint en "sprint final"
			//   et on le rallonge pour qu'il se termine en meme temps que la release
			if (m_listeSprint.size()>0 && (new Date(m_listeSprint.get(m_listeSprint.size()-1).getDateFin().getTime() + 2*86400000).before(this.m_dateFin))) {
				creerSprint(u.newSprint("sprint final",
						new Date(m_listeSprint.get(m_listeSprint.size()-1).getDateFin().getTime() + 2*86400000), 
						this.m_dateFin, 
						""));		
			}
			else if (m_listeSprint.size() == 0) {
				creerSprint(u.newSprint("sprint unique",
						this.m_dateDebut, 
						this.m_dateFin, 
						""));
			}
			else {
				m_listeSprint.get(m_listeSprint.size()-1).setNom("sprint final");
				m_listeSprint.get(m_listeSprint.size()-1).setDateFin(this.m_dateFin);
			}
		}
		else {
			creerSprint(u.newSprint("sprint final", dateDebut, dateFin, ""));
		}
		
			
		
//      Sauvegarde
        this.careTaker = new CareTaker<Release_State>();
        this.originator = new Originator<Release_State>(null);		
		
	}//Constructeur
	
	public Projet getProjet(){
		return this.m_projet;
	}
	
	public String getNom()
	{
		return this.m_nom;
	}
	
	public String getObjectif()
	{
		return this.m_objectif;
	}
	
	public Date getDateDebut()
	{
		return this.m_dateDebut;
	}
	
	public Date getDateFin()
	{
		return this.m_dateFin;
	}
	
	public void setNom(String n)
	{
		this.m_nom = n;
	}
	
	public void setObjectif( String o )
	{
		this.m_objectif = o;
	}
	
	public void setDateDebut( Date db )
	{
		this.m_dateDebut = db;
	}
	
	public void setDateFin( Date df )
	{
		this.m_dateFin = df;
	}
	
	public void creerSprint( Sprint s )
	{
		m_listeSprint.add(s);
	}
    
	public Sprint getSprint(int index){
        return m_listeSprint.get(index);
    }
	
	/**
	 * 
	 * @param nomFichier
	 * @param u
	 * @param projet : qui fait appelle e la restauration d'une release
	 * @return
	 */
	public static Release getReleaseFromXml(String nomFichier,Usine u, Projet projet){
		
		SAXBuilder sxb = new SAXBuilder();
		try {
			document = sxb.build(new File(nomFichier));
		} catch (JDOMException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		try
		{
	        document = sxb.build(new File(nomFichier));
	     }
	     catch(Exception e){}

	    //On initialise un nouvel element racine avec l'element racine du document.
	    racine = document.getRootElement();
	     
	    List<?> l = racine.getChildren();
	     
	 	String nom        = (String) l.get(0);
		String objectifs  = (String) l.get(1);
		Date dateDebut    = (Date) l.get(2);
		Date dateFin      = (Date) l.get(3);
		
		return new Release(u, projet, nom, objectifs, dateDebut, dateFin);
	}

	@Override
	public void save() {
//		Creation d'un memento et ajout au careTaker
		originator.setState(new Release_State(this)); //faire un clone ??
		careTaker.addMemento(originator.saveToMemento());
		Iterator<Sprint> it = this.getM_listeSprint().iterator();
		while(it.hasNext()){
			it.next().save();
		}
	}

	@Override
	public void saveToXML(String nomRepertoire) {
//		tester si le state != null
		Release r_saved = careTaker.getMemento(0).getSaveState().getRelease();
		
//		TODO : GERER LA LISTE DES SPRINTS
		
//		Creation du Document XML avec une racine
        racine = new Element("Release");
        racine.setAttribute(new Attribute("titre",r_saved.getNom()));
        document = new Document(racine);
        
		Element personnes = new Element("titre");
		personnes.setText(r_saved.getNom());
		racine.addContent(personnes);
	
		Element objectif = new Element("objectif");
		objectif.setText(r_saved.getObjectif());
		racine.addContent(objectif);
		
//		----------Date Debut----------
		Element dateDebut = new Element("Date_de_debut");
		racine.addContent(dateDebut);
		
		Date dbd = r_saved.getDateDebut();
//		jour
		Element jourD  = new Element("jour");
		jourD.setText(String.valueOf(dbd.getDate()));
		dateDebut.addContent(jourD);
//		mois
		Element moisD  = new Element("mois");
		moisD.setText(String.valueOf(dbd.getMonth()+1)); //janvier = 00
		dateDebut.addContent(moisD);
//		annee
		Element anneeD = new Element("annee");
		anneeD.setText(String.valueOf(dbd.getYear()+1900)); //current_date = current_date-1900
		dateDebut.addContent(anneeD);
		
//		----------Date Fin----------
		Element dateFin = new Element("Date_de_fin");
		racine.addContent(dateFin);
		
		Date dbF = r_saved.getDateFin();
//		jour
		Element jourF  = new Element("jour");
		jourF.setText(String.valueOf(dbF.getDate()));
		dateFin.addContent(jourF);
//		mois
		Element moisF  = new Element("mois");
		moisF.setText(String.valueOf(dbF.getMonth()+1)); //janvier = 00
		dateFin.addContent(moisF);
//		annee
		Element anneeF = new Element("annee");
		anneeF.setText(String.valueOf(dbF.getYear()+1900));  //current_date = current_date-1900
		dateFin.addContent(anneeF);
		
//		Ajout des noms des Sprints de la Release
		Iterator<Sprint> it = r_saved.getM_listeSprint().iterator();
		Element sprints = new Element("Sprints");
		sprints.setAttribute(new Attribute("taille", String.valueOf(r_saved.getM_listeSprint().size())));
		
		racine.addContent(sprints);
		while(it.hasNext()){
			Sprint s = it.next();
			Element sprint = new Element("Sprint");
			sprint.setText(s.getNom());
			sprints.addContent(sprint);
//			On la sauvegarde dans son fichier
			s.saveToXML(nomRepertoire);
		}		
		
//		Enregistre dans un fichier XML
		enregistre(nomRepertoire+"/"+r_saved.getNomFichier()+".xml",document);
	}

	public static CRelease restoreFromXML(String nomFichier,String nomRepertoire,Usine u, CProjet projet) {
		//On cree une instance de SAXBuilder
		Document doc = null;
		SAXBuilder sxb = new SAXBuilder();
		try
		{
			//On cree un nouveau document JDOM avec en argument le fichier XML
	        //Le parsing est termine ;)
			doc = sxb.build(new File(nomRepertoire+"/"+nomFichier));
	     }
	     catch(Exception e){}

	     //On initialise un nouvel element racine avec l'element racine du document.
	     racine = doc.getRootElement();
	     
	    List<?> l = racine.getChildren();
	     
		String nom = (String) ((Element) l.get(0)).getText();;
		String objectif = (String) ((Element) l.get(1)).getText();;
		
//		Recuperation de la Date de debut
		List<?> listeDateD = ((Element) l.get(2)).getChildren();
		int jourD  = Integer.valueOf((String) ((Element) listeDateD.get(0)).getText());
		int moisD  = Integer.valueOf((String) ((Element) listeDateD.get(1)).getText());
		int anneeD = Integer.valueOf((String) ((Element) listeDateD.get(2)).getText());

		@SuppressWarnings("deprecation")
		Date dateDebut = new Date(anneeD, moisD-1, jourD); 

//		Recuperation de la Date de fin
		List<?> listeDateF = ((Element) l.get(3)).getChildren();
		int jourF  = Integer.valueOf((String) ((Element) listeDateF.get(0)).getText());
		int moisF  = Integer.valueOf((String) ((Element) listeDateF.get(1)).getText());
		int anneeF = Integer.valueOf((String) ((Element) listeDateF.get(2)).getText());

		@SuppressWarnings("deprecation")
		Date dateFin = new Date(anneeF, moisF-1, jourF); 
		
//		TODO: ArrayList<Sprint> listeRelease = new ArrayList<Sprint>();
		
//	    Construction d'une nouvelle release
	    CRelease r_restored = new CRelease(u, projet, nom, objectif, dateDebut, dateFin);
	    
//	    Restauration de la liste des sprints
		ArrayList<Sprint> listeSprint = new ArrayList<Sprint>();
		Element liste = (Element) l.get(4);
		List<?> listeSprints = liste.getChildren();
		
		int taille_liste = Integer.valueOf(liste.getAttributeValue("taille"));
		for(int i=0;i<taille_liste;i++){
			listeSprint.add(Sprint.restoreFromXML((((Element) listeSprints.get(i)).getText()+".xml"),nomRepertoire, r_restored.getProjet().getBacklog())); //On recupere les sprints 
																								//dans leur fichier grece e leur nom
		}
//		setter la liste des sprints
		r_restored.setListeSprint(listeSprint);
		
	    return r_restored;
	}

         public void modifierRelease(String nom, String obj, Date debut, Date fin){
        setNom(nom);
        setObjectif(obj);
        setDateDebut(debut);
        setDateFin(fin);
      }

      public ArrayList<Sprint> getM_listeSprint() {
        return m_listeSprint;
      }
      
      public void setListeSprint(ArrayList<Sprint> l){
    	  this.m_listeSprint = l;
      }

	@Override
	public void restore() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String getNomFichier() {
		return this.m_nom;
	}
	
}
